﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net.Appender;
using MongoDB.Bson;
using log4net.Core;
using MongoDB.Driver;
using log4net.Layout;

namespace CYTS.Aoyou.Framework.Log
{
    /// <summary>
    /// 日志Mongodb操作者
    /// </summary>
    public class AoyouLogMongoDBAppender : AppenderSkeleton
    {
        private readonly List<MongoAppenderField> _fields = new List<MongoAppenderField>();

        /// <summary>
        /// 连接字符串
        /// </summary>
        public string ConnectionString { get; set; }

        /// <summary>
        /// 集合名称
        /// </summary>
        public string CollectionName { get; set; }

        /// <summary>
        /// 增加MongoAppenderFileld
        /// </summary>
        /// <param name="fileld"></param>
        public void AddField(MongoAppenderField fileld)
        {
            _fields.Add(fileld);
        }

        protected override void Append(LoggingEvent loggingEvent)
        {
            var collection = GetCollection();
            collection.Insert(BuildBsonDocument(loggingEvent));
        }

        protected override void Append(LoggingEvent[] loggingEvents)
        {
            var collection = GetCollection();
            collection.InsertBatch(loggingEvents.Select(BuildBsonDocument));
        }

        private MongoCollection GetCollection()
        {
            var db = GetDatabase();
            MongoCollection collection = db.GetCollection(CollectionName ?? "logs");
            return collection;
        }

        private MongoDatabase GetDatabase()
        {
            MongoUrl url = MongoUrl.Create(ConnectionString);
            var client = new MongoClient(url);
            MongoServer conn = client.GetServer();
            MongoDatabase db = conn.GetDatabase(url.DatabaseName ?? "log4net");
            return db;
        }

        private BsonDocument BuildBsonDocument(LoggingEvent log)
        {
            var doc = new BsonDocument();
            foreach (MongoAppenderField field in _fields)
            {
                object value = field.Layout.Format(log);
                var bsonValue = value as BsonValue ?? BsonValue.Create(value);
                doc.Add(field.Name, bsonValue);
            }
            return doc;
        }
    }

    /// <summary>
    /// Mongodb的字段
    /// </summary>
    public class MongoAppenderField
    {
        public string Name { get; set; }
        public IRawLayout Layout { get; set; }
    }
}
